﻿using System;
using System.Collections.Generic;
using System.Text;
using Core;

namespace Generators
{
    public class CPlusPlusCodeGenerator : CodeGenerator
    {
        public CPlusPlusCodeGenerator(ImplicitDefinition id)
            : base(id)
        {
            _Language = Language.CPlusPlus;
        }

        /// <summary>
        /// Declare function
        /// </summary>
        /// <returns></returns>
        protected override String DeclareInputFunction()
        {
            StringBuilder buider = new StringBuilder();

            buider.AppendFormat("void Input_{0}(", _ImDefination.Function.Name);
            for (int i = 0; i < _ImDefination.Function.Arguments.Count; ++i)
            {
                Argument arg = _ImDefination.Function.Arguments[i];
                buider.AppendFormat(DeclareRefVariable(arg.Type.MapToLanguage(_Language), arg.Name));
                if (i < _ImDefination.Function.Arguments.Count - 1)
                    buider.Append(", ");
            }

            buider.AppendFormat(")");

            return buider.ToString();
        }

        /// <summary>
        /// Declare output function
        /// </summary>
        /// <returns></returns>
        protected override String DeclareOutputFunction()
        {
            StringBuilder buider = new StringBuilder();

            buider.AppendFormat("void Output_{0}({1} {2})",
                                _ImDefination.Function.Name,
                                _ImDefination.Function.Result.Type.MapToLanguage(_Language),
                                _ImDefination.Function.Result.Name);

            return buider.ToString();
        }

        /// <summary>
        /// Declare main function
        /// </summary>
        /// <returns></returns>
        protected override String DeclareMainFunction()
        {
            return "void Main()";
        }

        /// <summary>
        /// Begin a function with {
        /// </summary>
        /// <returns></returns>
        protected override String BeginFunction()
        {
            return "{";
        }

        /// <summary>
        /// End a function with }
        /// </summary>
        /// <returns></returns>
        protected override String EndFunction()
        {
            return "}";
        }

        /// <summary>
        /// Declare variable
        /// </summary>
        protected override String DeclareVariable(DataType dataType, String varName)
        {
            return String.Format("\t{0} {1};", dataType.MapToLanguage(_Language), varName);
        }

        /// <summary>
        /// Declare reference variable
        /// </summary>
        protected override String DeclareRefVariable(String dataType, String varName)
        {
            return String.Format("{0} &{1}", dataType, varName);
        }

        /// <summary>
        /// Prompt input from user for a variable
        /// </summary>
        /// <param name="varName"></param>
        /// <returns></returns>
        protected override String PromptInput(String varName)
        {
            return String.Format("\tcout << \"Please input a value for {0}: \";", varName);
        }

        /// <summary>
        /// Prompt output 
        /// </summary>
        protected override String WriteOutput()
        {
            return String.Format("\tcout << {0} ;", _ImDefination.Function.Result.Name);
        }

        /// <summary>
        /// Read input from user for a variable
        /// </summary>
        protected override String ReadInput(String varName, DataType dataType)
        {
            // read the value from user
            return String.Format("\tcin >> {0};", varName);
        }

        /// <summary>
        /// Call input function
        /// </summary>
        /// <returns></returns>
        protected override String CallInputFunction()
        {
            StringBuilder buider = new StringBuilder();

            buider.AppendFormat("\tInput_{0}(", _ImDefination.Function.Name);
            for (int i = 0; i < _ImDefination.Function.Arguments.Count; ++i)
            {
                Argument arg = _ImDefination.Function.Arguments[i];
                buider.Append(arg.Name);
                if (i < _ImDefination.Function.Arguments.Count - 1)
                    buider.Append(", ");
            }

            buider.AppendFormat(");");
            return buider.ToString();
        }

        /// <summary>
        /// Call output function
        /// </summary>
        /// <returns></returns>
        protected override String CallOutputFunction()
        {
            return String.Format("\tOutput_{0}({1});", _ImDefination.Function.Name, _ImDefination.Function.Result.Name);
        }

        /// <summary>
        /// Call this function
        /// </summary>
        /// <returns></returns>
        protected override String CallThisFunction()
        {
            StringBuilder buider = new StringBuilder();

            buider.AppendFormat("\t{0} = {1}(", _ImDefination.Function.Result.Name, _ImDefination.Function.Name);
            for (int i = 0; i < _ImDefination.Function.Arguments.Count; ++i)
            {
                Argument arg = _ImDefination.Function.Arguments[i];
                buider.AppendFormat(arg.Name);
                if (i < _ImDefination.Function.Arguments.Count - 1)
                    buider.Append(", ");
            }

            buider.AppendFormat(");");
            return buider.ToString();
        }
    }
}
